home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
accounts
/
adduser.000
/
adduser
/
adduser.shadow.1.5
/
xfdes.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-10
|
11KB
|
426 lines
/****************************************************************************\
** XFDES.C - FAST DES ENCRYPTION ALOGRITHM FUNCTIONS FOR TURBO-C **
******************************************************************************
** VAX/FDES Routines Modified By Doctor Dissector **
******************************************************************************
** Copyright (c) 1991, By Doctor Dissector Last Update: 03/04/91 **
\****************************************************************************/
/*
** XFDES - Version 1.05
** Copyright 1991 By Doctor Dissector
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
char xfdes_c_msg[]="xfdes v1.05 - 4/3/91 - (c)1991 - filename: xfdes.c";
/*=[ Include Files ]========================================================*/
#include "xfdes.h"
/*=[ Global Variables ]=====================================================*/
/* The C and D arrays used to calculate the key schedule. */
static obpb1 C[28], D[28];
/* Key schedule. Alternating longs with low and high bits of key.
** Low and high 24 bits of keys are stored alternately.
*/
sbpb24 KS[32];
/* The current block, divided into 2 halves. */
obpb1 L[32], R[32];
/* Tables that combine the S and P operations. */
sbpb24 S0L[64], S1L[64], S2L[64], S3L[64],
S4L[64], S5L[64], S6L[64], S7L[64],
S0H[64], S1H[64], S2H[64], S3H[64],
S4H[64], S5H[64], S6H[64], S7H[64];
/* It is slightly faster to indirect through this table than to specify
** the desired table directly.
*/
static sbpb24 *stt[] =
{
S0L, S0H,
S1L, S1H,
S2L, S2H,
S3L, S3H,
S4L, S4H,
S5L, S5H,
S6L, S6H,
S7L, S7H,
};
/*===========================================================================*/
/* Convert unsl in twenty-four bit contiguous format
** to six bits per byte format. Return result.
*/
static sbpb24
tfTOsixbit(tf)
ebpb24 tf;
{
sbpb24 res=0;
res |= (tf >> 0) & 077;
res |= (((tf >> 6) & 077) << 8);
res |= (((tf >> 12) & 077) << 16);
return(res | (((tf >> 18) & 077) << 24));
}
/*===========================================================================*/
/* Convert unsl in six bits per byte format
** to twenty-four bit contiguous format. Return result.
*/
static ebpb24
sixbitTOtf(sb)
sbpb24 sb;
{
ebpb24 res=0;
res |= ((sb >> 0) & 077);
res |= (((sb >> 8) & 077) << 6);
res |= (((sb >> 16) & 077) << 12);
return(res | (((sb >> 24) & 077) << 18));
}
/*===========================================================================*/
/* Set up the key schedule from the key. */
static void
fsetkey(key)
obpb1 *key;
{
reg int i, j, k;
obpb1 s, t;
/* First, generate C and D by permuting the key. The low order bit of each
** 8-bit char is not used, so C and D are only 28 bits apiece.
*/
for(i=0; i<28; i++) {
C[i]=key[PC1_C[i]];
D[i]=key[PC1_D[i]];
}
/* To generate Ki, rotate C and D according to schedule and pick up a
** permutation using PC2.
*/
for(i=0; i<32; i+=2) {
for(k=0 ; k<shifts[i/2]; k++) { /* rotate */
s=C[0];
t=D[0];
for(j=0; j<27; j++) {
C[j]=C[j+1];
D[j]=D[j+1];
}
C[27]=s;
D[27]=t;
}
/* Get Ki. Note C and D are concatenated. */
KS[i]=KS[i+1]=0;
for(j=0; j<24; j++) {
KS[i] |= ((sbpb24) C[PC2_C[j]] << j);
KS[i+1] |= ((sbpb24) D[PC2_D[j]] << j);
}
KS[i]=tfTOsixbit(KS[i]);
KS[i+1]=tfTOsixbit(KS[i+1]);
}
}
/*===========================================================================*/
/* Lookup an S-box entry.*/
static fbpb4
lookupS(tableno, t6bits)
unsl tableno;
sbpb6R t6bits;
{
sbpb6 fixed6bits;
fbpb4R r;
fbpb4 fixedr;
fixed6bits=(((t6bits >> 0) & 01) << 5)+
(((t6bits >> 1) & 01) << 3)+
(((t6bits >> 2) & 01) << 2)+
(((t6bits >> 3) & 01) << 1)+
(((t6bits >> 4) & 01) << 0)+
(((t6bits >> 5) & 01) << 4);
r=(fbpb4)S[(int)tableno][(int)fixed6bits];
fixedr=(((r >> 3) & 01) << 0)+
(((r >> 2) & 01) << 1)+
(((r >> 1) & 01) << 2)+
(((r >> 0) & 01) << 3);
return(fixedr);
}
/*===========================================================================*/
/* The payoff: encrypt a block. */
static void
xform(quarters, saltvalue)
sbpb24 *quarters;
sbpb24 saltvalue;
{
reg sbpb6 *dp;
reg int mi;
reg sbpb24 *kp, *kend, k;
static sbpb24 Dl, Dh;
sbpb24 Rl, Rh, Ll, Lh, negsalt;
negsalt = ~saltvalue;
Ll=Lh=Rl=Rh=0;
kend=&KS[32];
for(mi=24; mi>-1; mi--) {
for(kp=KS; kp<kend; ) {
reg sbpb24 **stp;
k=(Rl ^ Rh);
k &= (~negsalt);
Dl=(k ^( Rl ^ *kp++));
Dh=(k ^( Rh ^ *kp++));
stp=((sbpb24 **) stt);
dp=((sbpb6 *) & Dl);
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
dp=((sbpb6 *) & Dh);
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
Ll ^= (*stp++)[*dp];
Lh ^= (*stp++)[*dp++];
k=(Ll ^ Lh);
k &= (~negsalt);
Dl=(k ^ Ll ^ *kp++);
Dh=(k ^ Lh ^ *kp++);
stp=((sbpb24 **) stt);
dp=((sbpb6 *) & Dl);
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
dp=((sbpb6 *) & Dh);
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
Rl ^= (*stp++)[*dp];
Rh ^= (*stp++)[*dp++];
}
Ll ^= Rl;
Lh ^= Rh;
Rl ^= Ll;
Rh ^= Lh;
Ll ^= Rl;
Lh ^= Rh;
}
{
reg sbpb24 *qp;
qp=quarters;
*qp++=Ll;
*qp++=Lh;
*qp++=Rl;
*qp++=Rh;
}
}
/*===========================================================================*/
/* Final permutation. Takes input from globals L and R. */
static void
Fperm(block)
unsb *block;
{
reg int j, k;
for(j=0; j<64; j++) {
k=FP[j];
block[j]=((k<32) ? L[k] : R[k-32]);
}
}
/*===========================================================================*/
/* Inverse of E permutation. */
static void
undoe(fromarr, toarr)
obpb1 *fromarr, *toarr;
{
reg int j;
for(j=0; j<32; j++)
toarr[j]=fromarr[1+(j & 03)+6*(j >> 2)];
}
/*===========================================================================*/
static void
toBA64(quarters, onebits64)
reg sbpb24 *quarters;
obpb1 *onebits64;
{
int j;
static obpb1 tmpE[48];
reg unsb *onebits48;
reg sbpb24 quarter;
onebits48=tmpE;
quarter=sixbitTOtf(*quarters++);
for(j=0; j<24; j++)
*onebits48++=((quarter >> j) & 01);
quarter=sixbitTOtf(*quarters++);
for(j=0; j<24; j++)
*onebits48++=((quarter >> j) & 01);
undoe(tmpE,L);
onebits48=tmpE;
quarter=sixbitTOtf(*quarters++);
for(j=0; j<24; j++)
*onebits48++=((quarter >> j) & 01);
quarter=sixbitTOtf(*quarters++);
for(j=0; j<24; j++)
*onebits48++=((quarter >> j) & 01);
undoe(tmpE,R);
Fperm(onebits64);
}
/*===========================================================================*/
static char *
fcrypt(pw, salt)
const char *pw;
char *salt;
{
reg int i;
reg obpb1 j, c;
static obpb1 block[66];
static char iobuf[16];
static sbpb24 out96[4];
sbpb24 saltvalue=0;
for(i=0; i<66; i++)
block[i]=0;
for(i=0; ((c=*pw)!=NULL) && (i<64); pw++) {
for(j=0; j<7; j++, i++)
block[i]=((c >> (6-j)) & 01);
i++;
}
fsetkey(block);
for(i=0; i<2; i++) {
c=iobuf[i]=*salt++;
if (c>'Z')
c-=6;
if (c>'9')
c-=7;
c-='.';
for(j=0; j<6; j++)
saltvalue |= ((c >> j) & 01) << (6*i+j);
}
saltvalue=tfTOsixbit(saltvalue);
xform(out96, saltvalue);
toBA64(out96, block);
for(i=0; i<11; i++) {
c=0;
for(j=0; j<6; j++) {
c <<= 1;
c |= block[6*i+j];
}
c+='.';
if (c>'9')
c+=7;
if (c>'Z')
c+=6;
iobuf[i+2]=c;
}
iobuf[i+2]=0;
if (!iobuf[1])
iobuf[1]=iobuf[0];
return(iobuf);
}
/*===========================================================================*/
static void
init(tableno, lowptr, highptr)
unsl tableno;
sbpb24 *lowptr, *highptr;
{
reg int k, i;
static obpb1 tmp32[32];
static obpb1 tmpP32[32];
static obpb1 tmpE[48];
sbpb6R j;
for(j=0; j<64; j++) {
k=lookupS(tableno, j);
for(i=0; i<32; i++)
tmp32[i]=0;
for(i=0; i<4; i++)
tmp32[4*(int)tableno+i]=(obpb1)(k >> i) & 01;
for(i=0; i<32; i++)
tmpP32[i]=tmp32[P[i]-1];
for(i=0; i<48; i++)
tmpE[i]=tmpP32[(int)E[i]-1];
lowptr[j]=highptr[j]=0;
for(i=0; i<24; i++)
lowptr[(int)j] |= (unsl)tmpE[i] << i;
for(k=0, i=24; i<48; i++, k++)
highptr[(int)j] |= (unsl)tmpE[i] << k;
lowptr[j]=tfTOsixbit(lowptr[j]);
highptr[j]=tfTOsixbit(highptr[j]);
}
}
/*===========================================================================*/
static void
init_des(void)
{
init((unsl)0, S0L, S0H);
init((unsl)1, S1L, S1H);
init((unsl)2, S2L, S2H);
init((unsl)3, S3L, S3H);
init((unsl)4, S4L, S4H);
init((unsl)5, S5L, S5H);
init((unsl)6, S6L, S6H);
init((unsl)7, S7L, S7H);
}